import { Asset, AudioClip, Node, ParticleSystem2D, Prefab, Size, SpriteFrame } from "cc"
import { CGameData, initData } from "../../../app/GameDefine"
import { Scene } from "../../../scene/script/Scene"
import { Vector2, EModuleType, BaseModuleEvent, _scene, _audio, TResoucesUrl, DataLogicHelper, _ui, JS, ColliderGroup, CreatePrefabToEditorCC, LayoutCC, _resouces, IVector2, P2World, P2Group, P2ShapeEditorCC, TVectorSet, StateMackine, Sets, Collider2DEditorCC, Rectangle, _config_, winSize, LevelHelper, moduleMgr, _gameType, _timer, Maths, _prop, _login, EUILayer, NodeHelper, _guide, winCenterPostion, IUIModule, _main, _logic } from "../Main"
import { CCubeSize, CSceneData, ELogicDataState, EPropId, ILogicData } from "./define/LogicDefine"
import { EGameType, gameTypeModule } from "./define/GameTypeDefine"
import { TenLevelGameType } from "./gameType/TenLevelGameType"
import { ISelectionEntityData } from "../../../scene/script/entity/SelectionEntity"
import { TenlLogic } from "./logic/TenlLogic"
import { NuoLogic } from "./logic/NuoLogic"
import { NuoLevelGameType } from "./gameType/NuoLevelGameType"
import { NuoTodayGameType } from "./gameType/NuoTodayGameType"


const v2T = new Vector2()
const v2T2 = new Vector2()

@moduleMgr.add(EModuleType.logic)
export class LogicModule extends BaseModuleEvent {

    public readonly EventType = {
        RESET: "RESET",
        DURATION_CHANGE: "DURATION_CHANGE",
        FAIL: "FAIL",
    }

    public cubeSize = new Size()
    public offsetY = 20
    public scaleRatio = 0
    public offset = new Vector2()
    public size = new Vector2()
    public animIndex: number = -1

    public ten: TenlLogic = null!
    public nuo: NuoLogic = null!

    public get isTenGameType() { return _gameType.type == EGameType.index || _gameType.type == EGameType.tenLevel }
    public get _tenLevel(): TenLevelGameType { return gameTypeModule.get(EGameType.tenLevel) }
    public get _nuoLevel(): NuoLevelGameType { return gameTypeModule.get(EGameType.nuoLevel) }
    public get _nuoToday(): NuoTodayGameType { return gameTypeModule.get(EGameType.nuoToday) }
    private get scene() { return _scene.getCurrent<Scene>() }

    onCreate() {
        this.ten = new TenlLogic()
        this.nuo = new NuoLogic()
    }

    onLogic() {
        let isOnce = false
        _scene.once(_scene.EventType.CHANG_SUCCESS, () => {
            _audio.playMusic("sceneRes/audio/bgm")

            _timer.once(this, () => {
                // _gameType.type = EGameType.index
                if (_gameType.type == EGameType.none)
                    if (_login.isNewUser && initData.newUseEnterGame)
                        _gameType.type = EGameType.tenLevel
                    else
                        _gameType.type = EGameType.index

                isOnce = true

                _gameType.run(_gameType.type)
            }, 2 / 60)
        })

        _ui.on(_ui.EventType.OPEN, (url: string) => {
            if (url == initData.uiUrl.index) {
                // 显示默认方块
                if (isOnce)
                    _gameType.run(EGameType.index)
            }
            checkPropUI()
        })

        let checkPropUI = () => {
            let top = _ui.getTop((ui) => ui.url != initData.uiUrl.prop)

            if (top) {
                if (top == initData.uiUrl.index
                    || top == CGameData.SettingUrl
                    || top == CGameData.FailUrl
                    || top == CGameData.SuccessUrl
                    || top == CGameData.PropGetUrl
                )
                    _ui.open(initData.uiUrl.prop)
                else
                    _ui.close(initData.uiUrl.prop)
            }
            else
                _ui.close(initData.uiUrl.prop)
        }

        _ui.on(_ui.EventType.CLOSE_SCENE_ALL_DELAY, checkPropUI)

        for (let config of _config_.arr.prop) {
            _prop.setSinglesOpenUI(config.id, () => {
                _ui.open(CGameData.PropGetUrl, _prop.singles.get(config.id))
            })
        }

        _prop.on(_prop.EventType.PROP_SUB, (id: number) => {
            if (this.isTenGameType)
                switch (id) {
                    case EPropId.reset:
                        if (_logic.ten.hasResetConfig())
                            this.ten.resetConfig()
                        else {
                            _ui.tip("请使用消除道具")
                            _timer.callLater(this, () => {
                                _prop.singles.get(EPropId.reset).add(1)
                                _prop.emit(_prop.EventType.PROP_CHANGE)
                            })
                        }
                        break
                    case EPropId.remove:
                        this.ten.propRemove()
                        break
                    case EPropId.tip:
                        if (!this.ten.propTip()) {
                            _ui.tip("没有可消除的")
                            _timer.callLater(this, () => {
                                _prop.singles.get(EPropId.tip).add(1)
                                _prop.emit(_prop.EventType.PROP_CHANGE)
                            })
                        }
                        break
                }
            else {
                switch (id) {
                    case EPropId.reset:
                        this.nuo.resetConfig()
                        break
                    case EPropId.tip:
                        this.nuo.propTip()
                        break
                    case EPropId.remove:
                        this.nuo.propRemove()
                        break
                    case EPropId.time:
                        this._nuoToday.addTime(5 * 60)
                        break
                }
            }
        })


        _main.preLoadQueue
            .add(complete => _audio.load(CSceneData.audio.drag, undefined, complete))
            .add(complete => _resouces.loadPrefab(_ui.DefaultUrl.fly, complete))
            .add(complete => _resouces.loadPrefab(_ui.DefaultUrl.flyItem, complete))
            .add(complete => _resouces.loadPrefab(CGameData.ResetCardAnimUI, complete))
            .add(complete => _resouces.loadPrefab(CGameData.SettingUrl, complete))
            .add(complete => _resouces.loadPrefab(CGameData.FailUrl, complete))
            .add(complete => _resouces.loadPrefab(CGameData.SuccessUrl, complete))
            .add(complete => _resouces.loadPrefab(CGameData.PropGetUrl, complete))
            .add(complete => _resouces.loadPrefab(CGameData.LevelSelectUrl, complete))

    }

    public _create(size: TVectorSet, maxX = 0, addY = 0, addSpace = 0) {
        this.size.set(size)
        // 右上角
        this.animIndex = this.getPosByIndex(this.size.x - 1, this.size.y - 1, this.size)
        this.scaleRatio = this.createByScaleRatio(Math.max(maxX, this.size.x), this.size.y + addY, addSpace)

        // console.log("整体缩放比率:", this.scaleRatio)
        this.cubeSize.width = CCubeSize.width * this.scaleRatio
        this.cubeSize.height = CCubeSize.height * this.scaleRatio

        this.createByOffset(this.offset, this.size, this.offsetY, this.cubeSize)
    }

    public palyResetAnim(complete: () => void) {
        this.scene.clearTips()
        _ui.open(CGameData.ResetCardAnimUI, null!, () => {
            _timer.once(this, () => {
                _ui.close(CGameData.ResetCardAnimUI)

                complete()

                _logic.emit(_logic.EventType.RESET)
            }, 1)
        })
    }


    public getPosByIndex(x: number, y: number, size: Vector2) {
        if (x < 0
            || y < 0
            || x >= size.x
            || y >= size.y
        )
            return -1
        return x * size.y + y
    }

    public createByScaleRatio(maxX: number, maxY: number, addSpace: number) {
        // 动态撑大
        let max = .95
        let defaultW = maxX * CCubeSize.width

        let defaultH = maxY * CCubeSize.width + addSpace
        let ratioH = defaultH / (winSize().height * .68)
        if (ratioH > 1)
            ratioH = Math.max(.5, 1 / ratioH)
        else
            ratioH = 1
        if (!this.isTenGameType)
            ratioH = 1

        let ratio = defaultW / winSize().width
        if (ratio > 1)
            ratio = Math.max(.5, 1 / ratio)
        else
            ratio = .8
        return ratio * max * ratioH
    }

    public createByOffset(out: Vector2, size: Vector2, offsetY: number, cubeSize: Size) {
        Vector2.mul(v2T, size, cubeSize)

        out
            .set(cubeSize)
            .subSelf(v2T)
            .mulSelf(.5)

        out.y += offsetY
    }


    public getIndexByAabbCenter(out: Rectangle, index: Vector2, cubeSize: Size, offset: Vector2) {

        let w = cubeSize.width
        let h = cubeSize.height
        out.width = w
        out.height = h

        v2T.x = offset.x + index.x * w
        v2T.y = offset.y + index.y * h
        out.center = v2T
    }

}